package com.tavenli.services;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.tavenli.entity.DeviceCmdEntity;
import com.tavenli.entity.DeviceLogEntity;
import com.tavenli.entity.F18Device;
import com.tavenli.entity.PersonEntity;
import com.tavenli.entity.PersonTempleteEntity;
import com.tavenli.interceptors.ActiveUserListener;
import com.tavenli.model.PageData;
import com.tavenli.repository.DeviceCmdDao;
import com.tavenli.repository.RedisDaoDeviceLog;
import com.tavenli.repository.RedisDaoF18Device;
import com.tavenli.utils.ConstantsUtil;

@Service(value = "deviceCmdService")
public class DeviceCmdService {
	private static Logger logger = LoggerFactory
			.getLogger(UCenterService.class);

	@Autowired
	private DeviceCmdDao deviceCmdDao;
	@Autowired
	private RedisDaoF18Device redisDaoF18Device;
	@Autowired
	private UPersonService personService;
	@Autowired
	private DeviceLogService deviceLogService;
	@Autowired
	private RedisDaoDeviceLog redisDaoDeviceLog;
	/**
	 * 生成检查数据更新的命令
	 * 
	 * @return
	 */
	public String getCheckCmd() {
		return "CHECK\r\n";
	}

	/**
	 * 生成清理考勤记录的命令
	 * 
	 * @return
	 */
	public String getClearLogCmd() {
		return "CLEAR LOG\r\n";
	}

	/**
	 * 生成所有数据的命令
	 * 
	 * @return
	 */
	public String getClearAllDataCmd() {
		return "CLEAR LOG\r\n";
	}

	/**
	 * 生成获取设备配置信息的命令
	 * 
	 * @return
	 */
	public String getDeviceInfoCmd() {
		return "INFO\r\n";
	}

	/**
	 * 更新设备对应的设置
	 * 
	 * @param args
	 * @param val
	 * @return
	 */
	public String getSetDeviceOptionsCmd(String args, String val) {
		return String.format("SET OPTION %s=%s\r\n", args, val);
	}

	/**
	 * 生成重启设备命令
	 * 
	 * @return
	 */
	public String getRebootCmd() {
		return "REBOOT\r\n";
	}

	/**
	 * 获取重新加载参数的cmd命令，执行完getSetDeviceOptionsCmd方法后执行此方法
	 * 
	 * @return
	 */
	public String getReLoadOptionsCmd() {
		return "RELOAD OPTIONS\r\n";
	}
	/**
	 * 通过人获取要更新人的命令
	 * @param personEntity
	 * @return
	 */
	public String getPersonCmd(PersonEntity personEntity) {
		String userString="";
		userString=userString.format("USER PIN=%s\tName=%s\tPri=%s\tPasswd=%s\tCard=%s\tGrp=%s\tTZ=%s", personEntity.getPersonPin(),
				personEntity.getPersonName(),personEntity.getPersonPri(),personEntity.getPersonPasswd()==null?"":personEntity.getPersonPasswd(),
						personEntity.getPersonCard()==null?"":personEntity.getPersonCard(),
				personEntity.getPersonGrp(),personEntity.getPersonTZ());
		String cmdString="DATA "+userString+"\r\n";
		return cmdString;
	}
	
	/**
	 * 获取更新人指纹的命令
	 * @param personTempleteEntity
	 * @return
	 */
	public String getPersonTempleteCmd(PersonTempleteEntity personTempleteEntity) {
		String cmdString="";
		PersonEntity personEntity=personService.getPersonById(personTempleteEntity.getPersonId());
		if (null!=personEntity) {
			String fpString="";
			fpString=fpString.format("FP PIN=%s\tFID=%d\tSize=%d\tValid=%d\tTMP=%s",
					personEntity.getPersonPin(),personTempleteEntity.getFID(),
					personTempleteEntity.getTempleteSize(),personTempleteEntity.getTempleteValid(),
					personTempleteEntity.getTempleteTmp());
			cmdString="DATA "+fpString+"\r\n";
		}
		return cmdString;
		
	}
	

	public PageData<DeviceCmdEntity> getDeviceCmdList(Integer pageIndex,
			int pageSize, String sn) {
		PageData<DeviceCmdEntity> pageData = new PageData<DeviceCmdEntity>(
				pageIndex, pageSize);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("sn", sn);
		int totalCount = deviceCmdDao.queryDataCount(paramMap);
		List<DeviceCmdEntity> list = deviceCmdDao.queryPageData(
				pageData.getStartRow(), pageSize, paramMap);
		pageData.setTotalCount(totalCount);
		pageData.setPageData(list);
		return pageData;
	}
	@Transactional
	public void dealOneDeviceLog(String string, String sn) {
		if (string.startsWith("USER")) {
			dealUserLog(string.replace("USER ", ""),sn);
		}if (string.startsWith("FP")) {
			dealFPLog(string.replace("FP ", ""),sn);
		}else {
			//处理考勤记录
			dealAttendanceLog(string, sn);
		}
	}
	/**
	 * 处理考勤记录
	 * @param string
	 * @param sn
	 */
	private void dealAttendanceLog(String string, String sn) {
		logger.info(string);
		String [] allData=string.split("\t");
		if (allData.length==4) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date=null;
			try {
				date = sdf.parse(allData[1]);
			} catch (ParseException e) {
				logger.error("设备上次的考勤数据格式不正确");
				e.printStackTrace();
			}
			DeviceLogEntity deviceLogEntity=new DeviceLogEntity();
			deviceLogEntity.setCreateTime(new Date());
			deviceLogEntity.setLastUpdate(new Date());
			deviceLogEntity.setSn(sn);
			deviceLogEntity.setLogType(allData[2].equals("1")?"正常开门":"非法开门");
			deviceLogEntity.setDeviceEventDate(date);
			deviceLogEntity.setLogText("工号为："+allData[3]+"的用户开门");
			try {
				deviceLogService.save(deviceLogEntity);
			} catch (Exception e) {
				logger.error("保存考勤记录出错");
				e.printStackTrace();
			}
			//保存deviceLogEntity到当前登陆客户
			Map<String, HttpSession> activeSessions = ActiveUserListener.getSessionMaps();
	        Collection<HttpSession> sessionsCollection = activeSessions.values();//得到当前所有会话之集合
	        Iterator<HttpSession> iterSessions = sessionsCollection.iterator();
	        while (iterSessions.hasNext()) {
	        	HttpSession mySession = (HttpSession) iterSessions.next();
	        	System.out.println(mySession.getId());
	        	//保存及时记录给当前有效用户
	        	redisDaoDeviceLog.listLeftPush(ConstantsUtil.REDIS_SHOW_LOG_LIST+mySession.getId(), JSONObject.fromObject(deviceLogEntity).toString());
	        }
		}
	}
	/**
	 * 当前用户访问时候获取可以看到的开门记录
	 * @param sessionId
	 * @return
	 */
	public List<DeviceLogEntity> getDeviceLogEntityBySessionId(String sessionId) {
		if(redisDaoDeviceLog.hasKey(ConstantsUtil.REDIS_SHOW_LOG_LIST+sessionId)){
			List<DeviceLogEntity> list=new ArrayList<DeviceLogEntity>();
			long listSize=redisDaoDeviceLog.listSize(ConstantsUtil.REDIS_SHOW_LOG_LIST+sessionId);
			if(listSize>5)
				listSize=5;
			for (int i = 0; i < listSize; i++) {
				String jsonString=redisDaoDeviceLog.listRightPop(ConstantsUtil.REDIS_SHOW_LOG_LIST+sessionId);
				JsonConfig jsonConfig = new JsonConfig();
				jsonConfig.setRootClass(DeviceLogEntity.class);
				Map<String, Class> classMap = new HashMap<String, Class>();
				classMap.put("deviceLogEntity", DeviceLogEntity.class); // 指定JsonRpcRequest的request字段的内部类型
				jsonConfig.setClassMap(classMap);
				JSONObject deviceLogEntityObj = JSONObject.fromObject(jsonString);
				DeviceLogEntity deviceLogEntity = (DeviceLogEntity) JSONObject.toBean(deviceLogEntityObj,
						jsonConfig);
				list.add(deviceLogEntity);
			}
			return list;
		}else {
			return null;
		}
	}
	
	
	/**
	 * 处理指纹类
	 * @param sn 
	 * @param replace
	 */
	private void dealFPLog(String fpLog, String sn) {
		try {
			Map<String, String> map = getMapFromStr(fpLog);
			String pinString=map.get("PIN");
			int FID=Integer.parseInt(map.get("FID"));
			int Size=Integer.parseInt(map.get("Size"));
			int Valid=Integer.parseInt(map.get("Valid"));
			String TMP=map.get("TMP");
			PersonEntity personEntityTemp = personService.getPersonByPin(pinString);
			if (null!=personEntityTemp) {
				PersonTempleteEntity personTempleteEntity=new PersonTempleteEntity();
				personTempleteEntity.setPersonId(personEntityTemp.getId());
				personTempleteEntity.setFID(FID);
				personTempleteEntity.setTempleteValid(Valid);
				personTempleteEntity.setTempleteSize(Size);
				personTempleteEntity.setTempleteTmp(TMP);
				personService.addOrUpdatePersonTemplete(personTempleteEntity);
			}else {
				//人未上来，指纹先上来，处理人员信息
				dealUserLog("PIN="+pinString+"\tCard=\tName=\tPri=0\tPasswd=\tGrp=0\tTZ=0000000000000000",sn);
				dealFPLog(fpLog,sn);//再次处理指纹信息
			}
		} catch (Exception e) {
			logger.debug("处理指纹命令信息错误：命令为："+fpLog);
		}
	}
	private void dealUserLog(String string, String sn) {
		try {
			Map<String, String> map = getMapFromStr(string);
			String pinString=map.get("PIN");
			PersonEntity personEntity = new PersonEntity();
			personEntity.setPersonCard(map.get("Card"));
			personEntity.setPersonName(map.get("Name"));
			personEntity.setPersonPin(pinString);
			personEntity.setPersonPri(map.get("Pri"));
			personEntity.setPersonPasswd(map.get("Passwd"));
			personEntity.setPersonGrp(map.get("Grp"));
			personEntity.setPersonTZ(map.get("TZ"));
			personEntity.setPersonStatus(1);
			personEntity.setLastUpdate(new Date());
			personEntity.setPersonOldSn(sn);
			if (!existPin(pinString)) {
				personEntity.setCreateTime(new Date());
				personService.save(personEntity);
			}else {
				PersonEntity personEntityTemp = personService.getPersonByPin(pinString);
				personEntity.setId(personEntityTemp.getId());
				personService.update(personEntity);
			}
			
		} catch (Exception e) {
			logger.debug("处理人员命令或保存人员信息错误：命令为："+string);
		}
	}

	private boolean existPin(String pinString) {
		return personService.existPersonByPin(pinString);
	}

	private Map<String, String> getMapFromStr(String string) {
		Map<String, String> map = new HashMap<String, String>();
		String[] stringArray = string.split("\t");
		for (int i = 0; i < stringArray.length; i++) {
			String[] tmp = stringArray[i].split("=");
			if (tmp.length >= 2) {
				map.put(tmp[0], tmp[1]);
			}
		}
		return map;
	}
	private Map<String, String> getMapFromStr(String string,String split) {
		Map<String, String> map = new HashMap<String, String>();
		String[] stringArray = string.split(split);
		for (int i = 0; i < stringArray.length; i++) {
			String[] tmp = stringArray[i].split("=");
			if (tmp.length >= 2) {
				map.put(tmp[0], tmp[1]);
			}
		}
		return map;
	}
	
	

	public void dealOneDeviceRet(String string) {
		try {
			if (string.startsWith("ID=")) {
				Map<String, String> firstRetMap=getMapFromStr(string,"&");
				int cmdId=Integer.parseInt(firstRetMap.get("ID"));
				DeviceCmdEntity deviceCmdEntity=new DeviceCmdEntity();
				deviceCmdEntity=deviceCmdDao.getDeviceCmdById(cmdId);
				if (null!=deviceCmdEntity) {
					int retVal=Integer.parseInt(firstRetMap.get("Return"));
					String typeString=firstRetMap.get("CMD");
					deviceCmdEntity.setCmdType(typeString);
					deviceCmdEntity.setRet(retVal);
					deviceCmdEntity.setLastUpdate(new Date());
					deviceCmdDao.update(deviceCmdEntity);
				}
			}else
			{
				logger.info("处理接收到的返回值数据为："+string);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生成删除指纹命令
	 * @param personTempleteEntity
	 */
	public String getDelPersonTempleteCmd(PersonTempleteEntity personTempleteEntity,PersonEntity personEntity)
	{
		return String.format("DEL_FP PIN=%d\tFID=%d", personEntity.getPersonPin(),personTempleteEntity.getFID());
	}
	public String getDelPersonCmd(PersonEntity personEntity)
	{
		return String.format("DEL_USER PIN=%d", personEntity.getPersonPin());
	}

	/**
	 *发送删除人员命令给设备，这里只要将其保存到redis中即可
	 * @param delCmdString
	 * @param personOldSn
	 * @throws Exception 
	 */
	public void sendCmdToDevice(String delCmdString, String sn) throws Exception
	{
		DeviceCmdEntity deviceCmdEntity=new DeviceCmdEntity();
		deviceCmdEntity.setCmd(delCmdString);
		deviceCmdEntity.setSn(sn);
		deviceCmdEntity.setCreateTime(new Date());
		deviceCmdEntity.setLastUpdate(new Date());
		deviceCmdEntity=(DeviceCmdEntity) deviceCmdDao.saveAndRet(deviceCmdEntity);
		String cmdString=String.format("C:%d:%s", deviceCmdEntity.getId(),delCmdString);
		redisDaoF18Device.listLeftPush(ConstantsUtil.REDIS_DEVICE_CMD_LIST+sn, cmdString);
	}

	/**
	 * 获取未执行的cmd命令
	 * @since 2015年1月13日 下午5:27:08
	 * @return
	 * @throws Exception 
	 */
	public String getUnExecCmd(String sn) throws Exception
	{
		if (redisDaoF18Device.hasKey(ConstantsUtil.REDIS_DEVICE_CMD_LIST+sn))
		{
			//List<String> list=redisDaoF18Device.listTop1(ConstantsUtil.REDIS_DEVICE_CMD_LIST+sn);
			//return list.get(0);
			return redisDaoF18Device.listRightPop(ConstantsUtil.REDIS_DEVICE_CMD_LIST+sn);
		}else {
			sendCmdToDevice(getCheckCmd(),sn);
			return null;
		}
	}
	@Transactional
	public int clearAllCmd() {
		return deviceCmdDao.deleteAll();
	}
	
}
